home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Source Code / C / Applications / Eudora 1.3.1 / source / nickmng.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-03-16  |  16.5 KB  |  594 lines  |  [TEXT/MPS ]

  1. #define FILE_NUM 2
  2. /* Copyright (c) 1990-1992 by the University of Illinois Board of Trustees */
  3. /************************************************************************
  4.  * routines to manage the nickname list
  5.  ************************************************************************/
  6. #pragma load EUDORA_LOAD
  7. #pragma segment NickMng
  8.  
  9. /************************************************************************
  10.  * The aliases list has the following structure:
  11.  * <length byte>name-of-alias<2 length bytes>expansion-of-alias...
  12.  * The aliases file contains lines of the form:
  13.  * "alias" name-of-alias expansion of alias<newline>
  14.  * Newlines may be escaped with "\".
  15.  * Lines not beginning with "alias" will be ignored
  16.  ************************************************************************/
  17.  
  18. /************************************************************************
  19.  * private functions
  20.  ************************************************************************/
  21. typedef struct
  22. {
  23.     Str31 name;
  24.     long offset;
  25. } AliasSortType, *AliasSortPtr, **AliasSortHandle;
  26.  
  27.     int ReadAliases(UHandle intoH,short cmdName);
  28.     Boolean NeatenLine(UPtr line, long *len);
  29.     short GatherCompAddresses(MyWindowPtr win,Handle biglist);
  30.     int BuildAliasInversion(AliasSortHandle *tableHP, long *count);
  31.     void AliasSortSwap(AliasSortPtr as1, AliasSortPtr as2);
  32. #define issep(c) (isspace(c) || (c)==',')
  33.  
  34. /************************************************************************
  35.  * RegenerateAliases - make sure the alias list is in memory
  36.  ************************************************************************/
  37. int RegenerateAliases(UHandle *intoH,short cmdName)
  38. {
  39.     int err=0;
  40.     
  41.     if (*intoH==nil)
  42.     {
  43.         *intoH=NuHandle(0L);
  44.         if (!*intoH) return(WarnUser(ALLO_ALIAS,MemError()));
  45.         err = ReadAliases(*intoH,cmdName);
  46.     }
  47.     else
  48.     {
  49.         HNoPurge(*intoH);
  50.         if (!**intoH)
  51.         {
  52.             ReallocHandle(*intoH,0);
  53.             if (!*intoH) return(WarnUser(ALLO_ALIAS,MemError()));
  54.             HNoPurge(*intoH);
  55.             err=ReadAliases(*intoH,cmdName);
  56.         }
  57.     }
  58.     if (err) ZapHandle(*intoH);
  59. #ifdef DEBUG
  60.     else ASSERT(GetHandleSize(*intoH));
  61. #endif
  62.     return(err);
  63. }
  64.  
  65. /************************************************************************
  66.  * ReadAliases - read the list of aliases
  67.  ************************************************************************/
  68. int ReadAliases(UHandle intoH,short cmdName)
  69. {
  70.     Str31 aliasFile;
  71.     Str31 aliasCmd;
  72.     int err;
  73.     Str255 line;
  74.     short expBytes;
  75.     UPtr spot,anchor,expSpot;
  76.     short type;
  77.     Boolean exLine=False;
  78.     long expOffset=0;
  79.     long len;
  80.     
  81.     GetRString(aliasFile,ALIAS_FILE);
  82.     GetRString(aliasCmd,cmdName);
  83.     if (err=OpenLine(MyVRef,MyDirId,aliasFile))
  84.         return(err==fnfErr ? noErr : FileSystemError(OPEN_ALIAS,aliasFile,err));
  85.     while ((type=GetLine(line,sizeof(line)))>0)
  86.     {
  87.         len = strlen(line);
  88.         if (exLine || type==LINE_MIDDLE)
  89.         {
  90.             if (expOffset)
  91.             {
  92.                 len = strlen(line);
  93.                 exLine = NeatenLine(line,&len);
  94.                 if (exLine && !issep(*line))
  95.                 {
  96.                     if (err=PtrAndHand(" ",intoH,1)) break;
  97.                     expBytes++;
  98.                 }
  99.                 if (err=PtrAndHand(line,intoH,len)) break;
  100.                 expBytes += len;
  101.             }
  102.         }
  103.         else
  104.         {
  105.             exLine = NeatenLine(line,&len);
  106.             if (expOffset)
  107.             {
  108.                 (*intoH)[expOffset] = expBytes >> 8;
  109.                 (*intoH)[expOffset+1] = expBytes & 0xff;
  110.                 expOffset = expBytes = 0;
  111.             }
  112.             if (len > *aliasCmd && !striscmp(line,aliasCmd+1))
  113.             {
  114.                 for (spot=line+*aliasCmd+1;issep(*spot);spot++);                /* skip ws */
  115.                 for (anchor=spot;*spot && !issep(*spot);spot++);                /* find name */
  116.                 for (expSpot=spot;issep(*expSpot);expSpot++);                     /* skip ws */
  117.                 if (*expSpot)                                                                                     /* valid */
  118.                 {
  119.                     anchor[-1] = MIN(MAX_NICKNAME,spot-anchor);
  120.                     if (err=PtrAndHand(anchor-1,intoH,anchor[-1]+3)) break;
  121.                     expOffset = GetHandleSize(intoH)-2;
  122.                     if (err=PtrAndHand(expSpot,intoH,len-(expSpot-line))) break;
  123.                     expBytes = len-(expSpot-line);
  124.                 }
  125.             }
  126.         }
  127.     }
  128.     CloseLine();
  129.     if (type    || err)
  130.         return(err ? WarnUser(ALLO_ALIAS,err) :
  131.                                             FileSystemError(READ_ALIAS,aliasFile,type));
  132.     if (expOffset)
  133.     {
  134.         (*intoH)[expOffset] = expBytes >> 8;
  135.         (*intoH)[expOffset+1] = expBytes & 0xff;
  136.         expOffset = 0;
  137.     }
  138.     return(noErr);
  139.  
  140. /************************************************************************
  141.  * NeatenLine - strip the newline from a line; if it was escaped, strip
  142.  * the backslash, and return True
  143.  ************************************************************************/
  144. Boolean NeatenLine(UPtr line, long *len)
  145. {
  146.     if (line[*len-1]=='\n') line[--*len] = 0;
  147.     if (line[*len-1]=='\\')
  148.     {
  149.         line[--*len] = 0;
  150.         return(True);
  151.     }
  152.     return(False);
  153. }
  154.  
  155.  
  156. /************************************************************************
  157.  * CountAliasTotal - how long is an alias (altogether)
  158.  ************************************************************************/
  159. long CountAliasTotal(UHandle aliases,long offset)
  160. {
  161.     return(CountAliasAlias(aliases,offset)+1+CountAliasExpansion(aliases,offset)+2);
  162. }
  163.  
  164. /************************************************************************
  165.  * CountAliasAlias - how long is the alias part of an alias (length byte
  166.  * not counted)
  167.  ************************************************************************/
  168. long CountAliasAlias(UHandle aliases,long offset)
  169. {
  170.     return ((unsigned) (*aliases)[offset]);
  171. }
  172.  
  173. /************************************************************************
  174.  * CountAliasExpansion - how long is an alias expansion (length word
  175.  * not counted)
  176.  ************************************************************************/
  177. long CountAliasExpansion(UHandle aliases,long offset)
  178. {
  179.     long base=offset+CountAliasAlias(aliases,offset)+1;
  180.     return (256*(unsigned)(*aliases)[base] + (unsigned)(*aliases)[base+1]);
  181. }
  182.  
  183.  
  184. /************************************************************************
  185.  * AddAlias - add an alias
  186.  ************************************************************************/
  187. short AddAlias(UHandle aliases,UPtr name,Handle addresses)
  188. {
  189.     long addrSize = addresses ? GetHandleSize(addresses) : 0;
  190.     long size = GetHandleSize(aliases);
  191.  
  192.     SetHandleBig(aliases,size+3+*name+addrSize);
  193.     if (MemError()) return(WarnUser(MEM_ERR,MemError()));
  194.     PCopy((*aliases)+size,name);
  195.     (*aliases)[size+*name+1] = addrSize>>8 & 0xff;
  196.     (*aliases)[size+*name+2] = addrSize & 0xff;
  197.     if (addrSize) BlockMove(*addresses,(*aliases+size+*name+3),addrSize);
  198.     return(0);
  199. }
  200.  
  201. /************************************************************************
  202.  * RemoveAlias - remove the named alias
  203.  ************************************************************************/
  204. void RemoveAlias(UHandle aliases,UPtr name)
  205. {
  206.     long oldSize=GetHandleSize(aliases);
  207.     long offset = FindAliasFor(aliases,name+1,*name);
  208.     long length;
  209.     if (offset >= 0)
  210.     {
  211.         length = CountAliasTotal(aliases,offset);
  212.         BlockMove((*aliases)+offset+length,(*aliases)+offset,
  213.                                                                                                     oldSize-offset-length);
  214.         SetHandleBig(aliases,oldSize-length);
  215.     }
  216. }
  217.  
  218. /************************************************************************
  219.  * ReplaceAlias - replace one nickname definition with another
  220.  ************************************************************************/
  221. short ReplaceAlias(UHandle aliases,UPtr oldName,UPtr newName,Handle text)
  222. {
  223.     short oldLength;
  224.     short newLength;
  225.     short eLen;
  226.     long size, newSize;
  227.     short maxAlias=GetRLong(BUFFER_SIZE)-40;
  228.     long offset= -1;
  229.     
  230.     if (oldName && *oldName) offset = FindAliasFor(aliases,oldName+1,*oldName);
  231.     if (offset<0) return(AddAlias(aliases,newName,text));
  232.     
  233.     /*
  234.      * grab the expansion
  235.      */
  236.     eLen = GetHandleSize(text);
  237.     
  238.     /*
  239.      * figure the sizes
  240.      */
  241.     oldLength = CountAliasTotal(aliases,offset);
  242.     newLength = *newName + eLen + 3;
  243.     if (newLength > maxAlias)
  244.     {
  245.         WarnUser(ALIAS_TOO_LONG, maxAlias);
  246.         eLen -= newLength-maxAlias;
  247.         newLength = maxAlias;
  248.     }
  249.             
  250.     /*
  251.      * do we need to expand?
  252.      */
  253.     if (newLength > oldLength)
  254.     {
  255.         size = GetHandleSize(aliases);
  256.         newSize = size+newLength-oldLength;
  257.         SetHandleBig(aliases,newSize);
  258.         if (MemError()) return(WarnUser(COULDNT_MOD_ALIAS,MemError()));
  259.         BlockMove((*aliases)+offset+oldLength,(*aliases)+offset+newLength,
  260.                                             size-offset-oldLength);
  261.     }
  262.  
  263.     /*
  264.      * put the bytes in
  265.      */
  266.     PCopy((*aliases)+offset,newName);
  267.     (*aliases)[offset+*newName+1] = (eLen>>8) & 0xff;
  268.     (*aliases)[offset+*newName+2] = eLen & 0xff;
  269.     BlockMove(*text,(*aliases)+offset+*newName+3,eLen);
  270.     
  271.     /*
  272.      * do we get to contract?
  273.      */
  274.     if (newLength<oldLength)
  275.     {
  276.         size = GetHandleSize(aliases);
  277.         newSize = size+newLength-oldLength;
  278.         BlockMove((*aliases)+offset+oldLength,(*aliases)+offset+newLength,
  279.                                             size-offset-oldLength);
  280.         SetHandleBig(aliases,newSize);
  281.     }
  282.     return(0);
  283. }
  284.  
  285. /************************************************************************
  286.  * MakeCompNick - make a nickname out of a comp window
  287.  ************************************************************************/
  288. void MakeCompNick(MyWindowPtr win)
  289. {
  290.     Handle biglist;
  291.     
  292.     biglist = NuHandle(0);
  293.     (void) GatherCompAddresses(win,biglist);
  294.  
  295.     /*
  296.      * and make the nickname...
  297.      */
  298.     if (**biglist) NewNick(biglist);
  299.     else WarnUser(NO_ADDRESSES,0);
  300.     
  301.     DisposeHandle(biglist);
  302. }
  303.  
  304. /************************************************************************
  305.  * GatherCompAddresses - gather the addresses from a window
  306.  ************************************************************************/
  307. short GatherCompAddresses(MyWindowPtr win,Handle biglist)
  308. {
  309.     Handle littlelist;
  310.     MessHandle messH;
  311.     static short heads[] = {TO_HEAD-1,CC_HEAD-1,BCC_HEAD-1};
  312.     short err=0;
  313.     short h;
  314.     
  315.     /*
  316.      * I vaant to suck your addresses...
  317.      */
  318.     messH = Win2MessH(win);
  319.     for (h=0;h<sizeof(heads)/sizeof(short);h++)
  320.     {
  321.         littlelist = SuckAddresses((*(*messH)->txes[heads[h]])->hText,
  322.                                                              (*(*messH)->txes[heads[h]])->teLength,True);
  323.         if (littlelist)
  324.         {
  325.           if (**littlelist)
  326.             {
  327.                 long size=GetHandleSize(biglist);
  328.                 if (size) SetHandleBig(biglist,size-1);    /* strip final terminator */
  329.                 HLock(littlelist);
  330.                 if (err=HandAndHand(littlelist,biglist)) break;
  331.             }
  332.             DisposeHandle(littlelist);
  333.         }
  334.     }
  335.     return(err);
  336. }
  337.  
  338. /************************************************************************
  339.  * MakeMessNick - make a nickname out of a message window
  340.  ************************************************************************/
  341. void MakeMessNick(MyWindowPtr win,short modifiers)
  342. {
  343.     TOCHandle out=GetOutTOC();
  344.     if (out)
  345.     {
  346.         Boolean wasDirty = (*out)->win->isDirty;
  347.         win = DoReplyMessage(win,modifiers | shiftKey,0,False);
  348.         if (!win) return;
  349.         MakeCompNick(win);
  350.         CloseMyWindow(win);
  351.         (*out)->win->isDirty = wasDirty;
  352.     }
  353. }
  354.  
  355. /************************************************************************
  356.  * MakeMboxNick - make a nickname out of the selected messages in an mbox
  357.  ************************************************************************/
  358. void MakeMboxNick(MyWindowPtr win,short modifiers)
  359. {
  360.     Handle addresses=NuHandle(0);
  361.     TOCHandle tocH = (TOCHandle)win->qWindow.refCon;
  362.     MyWindowPtr messWin,compWin;
  363.   short sumNum;
  364.     short err = 0;
  365.     Boolean isOut = (*tocH)->which==OUT;
  366.     
  367.     if (!addresses) return;
  368.     for (sumNum=0;!err && sumNum<(*tocH)->count;sumNum++)
  369.     {
  370.         if ((*tocH)->sums[sumNum].selected && ((*tocH)->sums[sumNum].messH || GetAMessage(tocH,sumNum,nil,False)))
  371.         {
  372.             messWin = (*(MessType **)(*tocH)->sums[sumNum].messH)->win;
  373.             compWin = isOut ? messWin : DoReplyMessage(messWin,modifiers,0,False);
  374.             if (compWin)
  375.             {
  376.                 err=GatherCompAddresses(compWin,addresses);
  377.                 if (compWin != messWin) CloseMyWindow(compWin);
  378.             }
  379.             if (!messWin->qWindow.visible) CloseMyWindow(messWin);
  380.         }
  381.     }
  382.     
  383.     if (!err)
  384.     {
  385.         if (**addresses) NewNick(addresses);
  386.         else WarnUser(NO_ADDRESSES,0);
  387.     }
  388.     
  389.     DisposeHandle(addresses);
  390. }
  391.  
  392. /************************************************************************
  393.  * MakeCboxNick - make a nickname out of the selected messages in Out
  394.  ************************************************************************/
  395. void MakeCboxNick(MyWindowPtr win)
  396. {
  397.     Handle addresses=NuHandle(0);
  398.     TOCHandle tocH = (TOCHandle)win->qWindow.refCon;
  399.     MyWindowPtr compWin;
  400.   short sumNum;
  401.     short err = 0;
  402.     
  403.     if (!addresses) return;
  404.     for (sumNum=0;!err && sumNum<(*tocH)->count;sumNum++)
  405.     {
  406.         if ((*tocH)->sums[sumNum].selected && 
  407.             ((*tocH)->sums[sumNum].messH || GetAMessage(tocH,sumNum,nil,False)))
  408.         {
  409.             compWin = (*(MessType **)(*tocH)->sums[sumNum].messH)->win;
  410.             if (compWin)
  411.             {
  412.                 err=GatherCompAddresses(compWin,addresses);
  413.                 if (!compWin->qWindow.visible) CloseMyWindow(compWin);
  414.             }
  415.         }
  416.     }
  417.     
  418.     if (!err)
  419.     {
  420.         if (**addresses) NewNick(addresses);
  421.         else WarnUser(NO_ADDRESSES,0);
  422.     }
  423.     
  424.     DisposeHandle(addresses);
  425. }
  426.  
  427. /************************************************************************
  428.  * FlattenListWith - make an address list one to a line
  429.  ************************************************************************/
  430. void FlattenListWith(Handle h,Byte c)
  431. {
  432.   UPtr from, to;
  433.     
  434.     from = to = *h;
  435.     while (*from)
  436.     {
  437.       while (*++from) *to++ = *from;    /* skip length byte, copy string */
  438.         from++;                                                    /* skip terminator */
  439.         *to++ = c;                                        /* and add a separator */
  440.     }
  441.     if (to > *h) to--;
  442.     SetHandleBig(h,to-*h);
  443. }
  444.  
  445. /************************************************************************
  446.  * SaveAliases - save the edited aliases (if necessary)
  447.  * returns False if the operation failed
  448.  ************************************************************************/
  449. Boolean SaveAliases(void)
  450. {
  451.     Str31 aliasFile,tmpFile;
  452.     Str31 aliasCmd;
  453.     Str63 scratch;
  454.     int err;
  455.     long max, offset;
  456.     long eLen;
  457.     long bytes;
  458.     short refN=0;
  459.     int i, count;
  460.     AliasSortHandle invers=nil;
  461.     
  462.     AliasWinGonnaSave();
  463.     GetRString(aliasFile,ALIAS_FILE);
  464.     PCopy(tmpFile,aliasFile);
  465.     GetRString(scratch,TEMP_SUFFIX);
  466.     PCat(tmpFile,scratch);
  467.     if (!Aliases || !*Aliases) {WarnUser(SAVE_ALIAS,0);goto done;}
  468.     if (RegenerateAliases(&Notes,NOTE_CMD)) goto done;
  469.     if (err=MakeResFile(tmpFile,MyVRef,MyDirId,CREATOR,MAILBOX_TYPE))
  470.         {FileSystemError(SAVE_ALIAS,tmpFile,err); goto done;}
  471.     if (err=FSHOpen(tmpFile,MyVRef,MyDirId,&refN,fsRdWrPerm))
  472.         {FileSystemError(OPEN_ALIAS,tmpFile,err); goto done;}
  473.         
  474.     max = GetHandleSize(Aliases);
  475.     if (BuildAliasInversion(&invers,&count)) count=max; /* hack */
  476.  
  477.     GetRString(aliasCmd,ALIAS_CMD);
  478.     PCatC(aliasCmd,' ');
  479.     LDRef(Aliases);
  480.     for (i=0;i<count;i++)
  481.     {
  482.         if (invers) offset = (*invers)[i].offset;
  483.         if (offset>max) break;                                         /* hack */
  484.         if (!(err = FSWriteP(refN,aliasCmd)))
  485.         {
  486.             PCopy(scratch,*Aliases+offset);
  487.             PCatC(scratch,' ');
  488.             if (!(err=FSWriteP(refN,scratch)))
  489.             {
  490.                 bytes = CountAliasExpansion(Aliases,offset);
  491.                 if (!(err = FSWrite(refN,&bytes,*Aliases+offset+*scratch+2)))
  492.                 {
  493.                     bytes = 1;
  494.                     err = FSWrite(refN,&bytes,"\n");
  495.                 }
  496.             }
  497.         }
  498.     }
  499.     if (invers) DisposHandle(invers);
  500.     UL(Aliases);
  501.     
  502.     GetRString(aliasCmd,NOTE_CMD);
  503.     PCatC(aliasCmd,' ');
  504.     LDRef(Notes);
  505.     eLen = GetHandleSize(Notes);
  506.     for (offset=0;offset<eLen;offset+=CountAliasTotal(Notes,offset))
  507.     {
  508.         if (!(err = FSWriteP(refN,aliasCmd)))
  509.         {
  510.             PCopy(scratch,*Notes+offset);
  511.             PCatC(scratch,' ');
  512.             if (!(err=FSWriteP(refN,scratch)))
  513.             {
  514.                 bytes = CountAliasExpansion(Notes,offset);
  515.                 if (!(err = FSWrite(refN,&bytes,*Notes+offset+*scratch+2)))
  516.                 {
  517.                     bytes = 1;
  518.                     err = FSWrite(refN,&bytes,"\n");
  519.                 }
  520.             }
  521.         }
  522.         if (err) {FileSystemError(SAVE_ALIAS,aliasFile,err); goto done;}
  523.     }
  524.     GetFPos(refN,&bytes);
  525.     SetEOF(refN,bytes);
  526.     AliasWinDidSave();
  527.  
  528.     /* do the deed */
  529.     if (err=HDelete(MyVRef,MyDirId,aliasFile))
  530.         {FileSystemError(SAVE_ALIAS,aliasFile,err); goto done;}
  531.     if (err=HRename(MyVRef,MyDirId,tmpFile,aliasFile))
  532.         FileSystemError(SAVE_ALIAS,aliasFile,err);
  533.  
  534. done:
  535.     if (Notes) UL(Notes);
  536.     if (Aliases) UL(Aliases);
  537.     if (refN) FSClose(refN);
  538.     return(err==noErr);
  539. }
  540.  
  541. /************************************************************************
  542.  * BuildAliasInversion - create a sort table for the aliases
  543.  ************************************************************************/
  544. int BuildAliasInversion(AliasSortHandle *tableHP, long *count)
  545. {
  546.     AliasSortHandle asH=nil;
  547.     int n=0;
  548.     int err=0;
  549.     long offset,max;
  550.     AliasSortType as;
  551.     int aLen;
  552.     
  553.     if (!(asH=NuHandle(0)))
  554.         err = MemError();
  555.     else
  556.     {
  557.         max = GetHandleSize(Aliases);
  558.         for (offset = 0; offset<max; offset += CountAliasTotal(Aliases,offset))
  559.         {
  560.             n++;
  561.             aLen = CountAliasAlias(Aliases,offset);
  562.             if (aLen >= sizeof(as.name)) aLen = sizeof(as.name)-1;
  563.             BlockMove((*Aliases)+offset,as.name,aLen+1);
  564.             as.offset = offset;
  565.             if (err=PtrAndHand(&as,asH,sizeof(as))) break;
  566.         }
  567.     }
  568.     
  569.     if (!err)
  570.     {
  571.         QuickSort(LDRef(asH),sizeof(as),0,n-1,StrCompar,AliasSortSwap);
  572.         UL(asH);
  573.         *tableHP = asH;
  574.         *count = n;
  575.     }
  576.     else
  577.         if (asH) DisposHandle(asH);
  578.     
  579.     return(err);
  580. }
  581.  
  582. /************************************************************************
  583.  * AliasSortSwap - swap two AliasSortType's
  584.  ************************************************************************/
  585. void AliasSortSwap(AliasSortPtr as1, AliasSortPtr as2)
  586. {
  587.     AliasSortType asTemp;
  588.     
  589.     asTemp = *as1;
  590.     *as1 = *as2;
  591.     *as2 = asTemp;
  592. }
  593.